package com.sky.service.impl;

import ch.qos.logback.core.joran.util.beans.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersPaymentDTO;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.*;
import com.sky.exception.OrderBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrdersService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.OrderPaymentVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.webSocket.WebSocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author hm
 * @package com.sky.service.impl
 * @date Created in 2024/11/22 19:06
 */
@Service
public class OrdersServiceImpl implements OrdersService {
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private WebSocketServer webSocketServer;
    @Autowired
    private WeChatPayUtil weChatPayUtil;

    /**
     * 用户下单
     *
     * @param ordersSubmitDTO
     * @return 1.通过传过来的地址簿查询地址，判断地址簿是否为空
     * 2.通过当前用户查询购物车，判断购物车是否为空
     * 3.向订单表中插入一条数据
     * 4.向订单详细表插入多条数据
     */
    @Transactional(rollbackFor = Exception.class)
    public OrderSubmitVO submit(OrdersSubmitDTO ordersSubmitDTO) {
        //获取用户id
        Long currentId = BaseContext.getCurrentId();
        //1.判断地址簿是否为空（通过用户id获取账户的地址簿，判断是否为空）
        AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
        if (addressBook == null) {
            throw new OrderBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }

        //根据userId查询到user用户，方便下面设置user用户
        User user = userMapper.selectById(currentId);
        if (user == null) {
            throw new OrderBusinessException(MessageConstant.USER_NOT_LOGIN);
        }

        //2.判断购物车是否为空（通过用户id获取购物车内容，判断是否为空）
        List<ShoppingCart> list = shoppingCartMapper.list(currentId);
        if (list == null || list.size() == 0) {
            throw new OrderBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }


        //3.向订单表插入一条数据
        Orders orders = new Orders();
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        //补全Order对象的属性值
        orders.setNumber(System.currentTimeMillis() + "");        //补全  订单编号
        orders.setStatus(Orders.PENDING_PAYMENT);               //补全  订单状态
        orders.setUserId(currentId);                            //补全  下单人的id
        orders.setOrderTime(LocalDateTime.now());               //补全  下单时间
        orders.setPayStatus(Orders.UN_PAID);                    //补全   支付状态
        //以下信息是用户信息，需要查询到用户信息
        orders.setPhone(addressBook.getPhone());                //补全   收货人电话号码
        orders.setAddress(addressBook.getDetail());             //补全   收货地址
        orders.setUserName(addressBook.getConsignee());         //补全   收货人
        orders.setConsignee(user.getName());                    //补全   下单人姓名

        ordersMapper.insert(orders);

        //4.向订单明细表插入多条数据(批量插入)
        List<OrderDetail> orderDetailList = new ArrayList<>();
        for (ShoppingCart shoppingCart : list) {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(shoppingCart, orderDetail);
            orderDetail.setOrderId(orders.getId());
            orderDetailList.add(orderDetail);
        }
        orderDetailMapper.insertBatch(orderDetailList);

        //清空购物车
        shoppingCartMapper.deleteById(currentId);

        //构建返回的对象OrderSubmitVO

        return OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderAmount(orders.getAmount())
                .orderTime(orders.getOrderTime())
                .build();
    }

    /**
     * 用户端的订单支付功能
     *根据订单id查询到订单信息
     * 修改订单的信息（支付方式、支付状态、支付时间）
     * 调用websocket向用户端广发消息(用户id、支付时间、支付状态、)
     */
    @Override
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) {
        //根据订单号和用户id查询订单信息
        Orders order = ordersMapper.getByNumberAndUserId(ordersPaymentDTO.getOrderNumber());
        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(order.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .payMethod(1)
                .checkoutTime(LocalDateTime.now())
                .build();
        ordersMapper.update(orders);
        shoppingCartMapper.delete(BaseContext.getCurrentId());
        //调用websocket向用户端广发消息
        Map map = new HashMap();
        map.put("type",1);
        map.put("orderId", order.getId());
        map.put("content", "订单号：" + order.getNumber());
        String Json = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(Json);
        return new OrderPaymentVO();

//        Long userId = BaseContext.getCurrentId();
//        // 根据订单号查询当前用户的订单
//        Orders ordersDB = ordersMapper.getByNumberAndUserId(ordersPaymentDTO.getOrderNumber(), userId);
//        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
//        Orders orders = Orders.builder()
//                .id(ordersDB.getId())
//                .status(Orders.TO_BE_CONFIRMED)
//                .payStatus(Orders.PAID)
//                .checkoutTime(LocalDateTime.now())
//                .build();
//        ordersMapper.update(orders);
//        Map map = new HashMap();
//        map.put("type", 1);//消息类型，1表示来单提醒
//        map.put("orderId", orders.getId());
//        map.put("content", "订单号：" + ordersDB.getNumber());
//        String jsonString = JSON.toJSONString(map);
//        webSocketServer.sendToAllClient(jsonString);
//        return new OrderPaymentVO();
    }
    /**
     * 用户催单功能
     * id——>用户id
     * 1.通过id查询到订单
     * 2.使用到websocket
     * 3.使用hashmap，websocket里面是（）
     * 4.发送的消息放进map集合发送到客户端(订单信息，提醒的类型、)
     */
    @Override
    public void reminder(Long id) {
        Orders orders = ordersMapper.getById(id);
        if (orders == null) {
            throw new RuntimeException(MessageConstant.ORDER_NOT_FOUND);
        }
        Map map = new HashMap<>();
        map.put("type", 1);//消息类型，1表示来单提醒,2表示催单
        map.put("orderId", id);
        map.put("订单号", orders.getNumber());
        String jsonString = JSON.toJSONString(map);
        webSocketServer.sendToAllClient(jsonString);
    }

    /**
     * 根据订单状态分页查询历史订单
     */
    public PageResult pageQueryUser(int pageNum, int pageSize, Integer status) {
        // 设置分页
        PageHelper.startPage(pageNum, pageSize);
        OrdersPageQueryDTO ordersPageQueryDTO = new OrdersPageQueryDTO();
        ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());
        ordersPageQueryDTO.setStatus(status);
        // 分页条件查询
        Page<Orders> page = ordersMapper.pageQuery(ordersPageQueryDTO);
        List<OrderVO> list = new ArrayList();
        // 查询出订单明细，并封装入OrderVO进行响应
        if (page != null && page.getTotal() > 0) {
            for (Orders orders : page) {// 订单id
                // 查询订单明细
                List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(orders.getId());
                OrderVO orderVO = new OrderVO();
                BeanUtils.copyProperties(orders, orderVO);
                orderVO.setOrderDetailList(orderDetails);
                list.add(orderVO);
            }
        }
        return new PageResult(page.getTotal(), list);
    }

    /**
     * 用户端查看详细信息
     */
    @Override
    public OrderVO details(Long id) {
        Orders orders = ordersMapper.getById(id);
        List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(orders, orderVO);
        orderVO.setOrderDetailList(orderDetailList);
        return orderVO;
    }

    /**
     *用户取消订单
     *  订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
     * 1.如果状态是 已接单或者是派送中的订单不能直接取消，需要和商家打电话沟通，同意后还要涉及退款
     * 2.如果是待接单或者待付款状态，可以直接修改订单的状态
     */
    @Override
    public void cancel(Long id) throws Exception {
        Orders orders = ordersMapper.getById(id);
        if (orders == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }
        if (orders.getStatus() > 2){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }
        orders.setStatus(Orders.CANCELLED);
        orders.setCancelReason("用户取消订单");
        orders.setCancelTime(LocalDateTime.now());
        ordersMapper.update(orders);
        //涉及到订单退款
        // 订单处于待接单状态下取消，需要进行退款
//        if (orders.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
//            //调用微信支付退款接口
//            weChatPayUtil.refund(
//                    orders.getNumber(), //商户订单号
//                    orders.getNumber(), //商户退款单号
//                    new BigDecimal(0.01),//退款金额，单位 元
//                    new BigDecimal(0.01));//原订单金额
//
//            //支付状态修改为 退款
//            orders.setPayStatus(Orders.REFUND);
//        }
    }

    @Override
    public void repetition(Long id) {
        /**
         * 通过id，将下单的订单的商品重新加入到购物车
         */
        List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);
        ShoppingCart shoppingCart = new ShoppingCart();
        //将订单详情添加进哪个用户的购物车
        shoppingCart.setUserId(BaseContext.getCurrentId());
        for (OrderDetail orderDetail : orderDetails) {
            BeanUtils.copyProperties(orderDetail, shoppingCart);
            shoppingCartMapper.insert(shoppingCart);
        }
    }

    /**
     * 用户端实现分页查询+历史搜索
     */
    @Override
    public PageResult pageQueryAdmin(OrdersPageQueryDTO ordersPageQueryDTO) {
        return null;
    }
}
